package sysytmRepo

import (
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"net/http"
	"ruoyi/domain/entity/common"
	"ruoyi/domain/entity/constants"
	"ruoyi/domain/entity/response"
	"ruoyi/domain/entity/system"
	"ruoyi/domain/repository"
	"ruoyi/interfaces/middleware"
	"ruoyi/utils"
	"strconv"
	"time"
)

type sysUserRepo struct {
	db *gorm.DB
}

func SysUserRepository(db *gorm.DB) *sysUserRepo {
	return &sysUserRepo{db}
}

var _ repository.SysUserRepository = &sysUserRepo{}

func (r *sysUserRepo) FindUserByName(loginName string) system.SysUser {
	var user system.SysUser
	err := r.db.Where("del_flag != 2 and user_name = ?", loginName).Find(&user).Error
	if err != nil {
		panic(response.ReturnFailMsg(err.Error()))
	}
	return user
}

func (r *sysUserRepo) IsAdminById(userId int) bool {
	return userId == 1
}

// IsAdmin 指定数据库表名称
func (r *sysUserRepo) IsAdmin(user *system.SysUser) bool {
	return user.UserId == 1
}

func (r *sysUserRepo) IsExistUser(loginName string) bool {
	var user system.SysUser
	err := r.db.Where("del_flag = 0 and user_name = ?", loginName).First(&user).Error
	if err != nil {
		return false
	}
	return true
}

func (r *sysUserRepo) IsExistUserByPhoneNumber(phoneNumber string) bool {
	var user system.SysUser
	err := r.db.Where("del_flag = 0 and phonenumber = ?", phoneNumber).First(&user).Error
	if err != nil {
		return false
	}
	return true
}

func (r *sysUserRepo) IsExistUserByEmail(email string) bool {
	var user system.SysUser
	err := r.db.Where("del_flag = 0 and email = ?", email).First(&user).Error
	if err != nil {
		return false
	}
	return true
}

func (r *sysUserRepo) FindUserById(id any) system.SysUser {
	userId := utils.GetInterfaceToInt(id)
	if userId < 1 {
		panic(response.ReturnFailMsg("获取用户信息失败"))
	}
	var user system.SysUser
	var db = r.db.Model(&user).
		Select("`sys_user`.*, d.dept_name, d.leader").
		Joins("left join sys_dept d on d.dept_id = `sys_user`.dept_id")
	db.Where("`sys_user`.del_flag = 0")
	err := db.Where("user_id = ?", userId).First(&user).Error
	if err != nil {
		panic(response.ReturnFailMsg(err.Error()))
	}
	user.Password = ""
	return user
}

/*校验用户是否有数据权限*/
func (r *sysUserRepo) CheckUserDataScope(userId int, useridP int) {
	if !r.IsAdminById(userId) {
		var param = common.SearchTableDataParam{
			Other: system.SysUser{
				UserId: useridP,
			},
		}
		var row = r.SelectUserList(param, false)
		if row.Rows == nil {
			panic(response.ReturnFailMsg("没有权限访问用户数据！"))
		}
	}
}

func (r *sysUserRepo) SelectUserList(params common.SearchTableDataParam, isPage bool) common.TableDataInfo {
	var pageNum = params.PageNum
	var pageSize = params.PageSize
	sysUser := params.Other.(system.SysUser)

	offset := (pageNum - 1) * pageSize
	var total int64
	var rows []system.SysUser

	var db = r.db.Model(&rows).
		Select("`sys_user`.*, d.dept_name, d.leader").
		Joins("left join sys_dept d on d.dept_id = `sys_user`.dept_id")

	db.Where("`sys_user`.del_flag = ?", "0")

	var userId = sysUser.UserId
	if userId != 0 {
		db.Where("`sys_user`.user_id = ?", userId)
	}
	var deptId = sysUser.DeptId
	if deptId != 0 {
		db.Where("`sys_user`.dept_id = ? OR `sys_user`.dept_id IN (SELECT t.dept_id FROM sys_dept t WHERE find_in_set(?, ancestors))", deptId, deptId)
	}

	var userName = sysUser.UserName
	if userName != "" {
		db.Where("`sys_user`.user_name like concat('%', ?, '%')", userName)
	}

	var status = sysUser.Status
	if status != "" {
		db.Where("`sys_user`.status = ? ", status)
	}

	var phonenumber = sysUser.PhoneNumber
	if phonenumber != "" {
		db.Where("`sys_user`.phonenumber = ? ", phonenumber)
	}
	var beginTime = params.Params.BeginTime
	var endTime = params.Params.EndTime

	if beginTime != "" {
		startTime1, endTime1 := utils.GetBeginAndEndTime(beginTime, endTime)
		db.Where("`sys_user`.create_time >= ?", startTime1)
		db.Where("`sys_user`.create_time <= ?", endTime1)
	}

	if err := db.Count(&total).Error; err != nil {
		return common.Fail()
	}

	if isPage {
		if err := db.Limit(pageSize).Offset(offset).Find(&rows).Error; err != nil {
			return common.Fail()
		}
	} else {
		if err := db.Find(&rows).Error; err != nil {
			return common.Fail()
		}
	}

	if rows == nil {
		return common.Fail()
	} else {
		return common.Success(rows, total)
	}
}

func (r *sysUserRepo) SelectUserParamList(params common.SearchTableDataParam, isPage bool) common.TableDataInfo {
	var pageNum = params.PageNum
	var pageSize = params.PageSize
	sysUser := params.Other.(system.SysUser)

	offset := (pageNum - 1) * pageSize
	var total int64
	var rows []system.SysUserExcel

	var db = r.db.Model(&rows).
		Select("`sys_user`.*, d.dept_name, d.leader").
		Joins("left join sys_dept d on d.dept_id = `sys_user`.dept_id")

	db.Where("`sys_user`.del_flag = ?", "0")

	var userId = sysUser.UserId
	if userId != 0 {
		db.Where("`sys_user`.user_id = ?", userId)
	}
	var deptId = sysUser.DeptId
	if deptId != 0 {
		db.Where("`sys_user`.dept_id = ? OR `sys_user`.dept_id IN (SELECT t.dept_id FROM sys_dept t WHERE find_in_set(?, ancestors))", deptId, deptId)
	}

	var userName = sysUser.UserName
	if userName != "" {
		db.Where("`sys_user`.user_name like concat('%', ?, '%')", userName)
	}

	var status = sysUser.Status
	if status != "" {
		db.Where("`sys_user`.status = ? ", status)
	}

	var phonenumber = sysUser.PhoneNumber
	if phonenumber != "" {
		db.Where("`sys_user`.phonenumber = ? ", phonenumber)
	}
	var beginTime = params.Params.BeginTime
	var endTime = params.Params.EndTime

	if beginTime != "" {
		startTime1, endTime1 := utils.GetBeginAndEndTime(beginTime, endTime)
		db.Where("`sys_user`.create_time >= ?", startTime1)
		db.Where("`sys_user`.create_time <= ?", endTime1)
	}

	if err := db.Count(&total).Error; err != nil {
		return common.Fail()
	}

	if isPage {
		if err := db.Limit(pageSize).Offset(offset).Find(&rows).Error; err != nil {
			return common.Fail()
		}
	} else {
		if err := db.Find(&rows).Error; err != nil {
			return common.Fail()
		}
	}

	if rows == nil {
		return common.Fail()
	} else {
		return common.Success(rows, total)
	}
}

func (r *sysUserRepo) GetUserDeptTree() []system.SysDeptDto {

	var param = common.SearchTableDataParam{
		Other: system.SysDept{},
	}

	var result, total = SysDeptRepository(r.db).GetDeptList(param, false)
	var data []system.SysDeptDto
	for i := 0; i < int(total); i++ {
		var bean = result[i]
		if bean.ParentId == 0 {
			dept := system.SysDeptDto{
				Id:    bean.DeptId,
				Label: bean.DeptName,
			}
			data = append(data, getDeptChildren(result, dept))
		}
	}

	return data
}

func getDeptChildren(list []system.SysDeptResult, dept system.SysDeptDto) system.SysDeptDto {
	var data []system.SysDeptDto
	for i := 0; i < len(list); i++ {
		var bean = list[i]
		if bean.ParentId == dept.Id {
			dept := system.SysDeptDto{
				Id:    bean.DeptId,
				Label: bean.DeptName,
			}
			data = append(data, getDeptChildren(list, dept))
		}
	}
	dept.Children = data
	return dept
}

func (r *sysUserRepo) ImportUserData(users []system.SysUserParam, updateSupport string) (string, string) {
	var errList []string
	var error string
	for i := 0; i < len(users); i++ {
		var u1 = users[i]
		u1.CreateTime = time.Now()
		var userName = u1.UserName
		var u2 = r.FindUserByName(userName)

		password := SysConfigRepository(r.db).SelectConfigByKey("sys.user.initPassword")
		var pwd = ""
		if password != "" {
			pwd, _ = utils.PasswordHash(password)
		} else {
			pwd, _ = utils.PasswordHash("123456")
		}

		u1.Password = pwd
		var d = strconv.Itoa(i + 1)
		if u2.UserId == 0 {
			err := r.SaveUser(u1)
			if err != "" {
				error = "error"
				errList = append(errList, d+"、用户名："+userName+"，添加失败<br/>")
			} else {
				errList = append(errList, d+"、用户名："+userName+"，添加成功<br/>")
			}
		} else {
			if updateSupport == "true" {
				userIds := make([]int, 0)
				userIds = append(userIds, u2.UserId)
				r.DeleteUser(userIds)
				err := r.SaveUser(u1)
				if err != "" {
					error = "error"
					errList = append(errList, d+"、用户名："+userName+"，添加失败<br/>")
				} else {
					errList = append(errList, d+"、用户名："+userName+"，添加成功<br/>")
				}
			} else {
				error = "error"
				errList = append(errList, d+"、用户名："+userName+"，已存在<br/>")
			}
		}
	}
	var result string
	for _, i := range errList {
		result += i
	}
	return error, result
}

func (r *sysUserRepo) SaveUser(user system.SysUserParam) string {
	var result = ""
	var u = system.SysUser{
		NickName:    user.UserName,
		DeptId:      user.DeptId,
		UserName:    user.UserName,
		UserType:    "00",
		Email:       user.Email,
		PhoneNumber: user.PhoneNumber,
		Sex:         user.Sex,
		Avatar:      user.Avatar,
		Password:    user.Password,
		LoginDate:   user.CreateTime,
		Status:      "0",
		DelFlag:     "0",
		CreateBy:    user.CreateBy,
		CreateTime:  user.CreateTime,
		UpdateTime:  user.CreateTime,
		Remark:      user.Remark,
	}
	err1 := r.db.Model(&system.SysUser{}).Create(&u).Error
	if err1 != nil {
		result = "" + err1.Error()
	}
	user.UserId = u.UserId
	SysPostRepository(r.db).AddPostByUser(user)
	SysRoleRepository(r.db).AddRolesByUser(user)
	return result
}

func (r *sysUserRepo) UploadUser(userParam system.SysUserParam) {
	var userIds = []int{userParam.UserId}
	roleService := SysRoleRepository(r.db)
	roleService.DeleteRolesByUser(userIds)
	roleService.AddRolesByUser(userParam)

	postService := SysPostRepository(r.db)
	postService.DeletePostByUser(userIds)
	postService.AddPostByUser(userParam)
	var user = system.SysUser{
		UserId:      userParam.UserId,
		DeptId:      userParam.DeptId,
		NickName:    userParam.NickName,
		PhoneNumber: userParam.PhoneNumber,
		Email:       userParam.Email,
		Sex:         userParam.Sex,
		Status:      userParam.Status,
		Remark:      userParam.Remark,
	}
	err := r.db.Updates(&user).Error
	if err != nil {
		panic(response.ReturnFailMsg("更新信息失败"))
	}
}

func (r *sysUserRepo) EditProfileUserInfo(userId int, param system.UserParam) response.Response {
	var user system.SysUser
	err1 := r.db.Where("user_id = ?", userId).First(&user)

	if err1.Error != nil {
		return response.ReturnFailMsg("未找到用户")
	}

	data := make(map[string]interface{})

	if param.NickName != "" {
		data["nick_name"] = param.NickName
	}

	if param.Email != "" {
		data["email"] = param.Email
	}

	if param.PhoneNumber != "" {
		data["phonenumber"] = param.PhoneNumber
	}

	if param.Sex != "" {
		data["sex"] = param.Sex
	}
	//等价于: UPDATE `foods` SET `price` = '35', `stock` = '0'  WHERE (user_id = '2')
	err2 := r.db.Model(&system.SysUser{}).Where("user_id = ?", userId).Updates(data)

	if err2.Error != nil {
		return response.ReturnFailMsg("修改失败")
	}

	return response.ReturnSuccess("修改成功")
}

func (r *sysUserRepo) DeleteUser(userId []int) response.Response {
	for _, v := range userId {
		if v == constants.AdminId {
			return response.ReturnFailMsg("管理员数据不开操作")
		}
	}
	// 删除部门管理
	SysPostRepository(r.db).DeletePostByUser(userId)
	// 删除角色管理
	SysRoleRepository(r.db).DeleteRolesByUser(userId)
	// 删除用户
	r.DeleteUserById(userId)
	return response.ReturnSuccess("操作成功")
}

func (r *sysUserRepo) DeleteUserById(userId []int) response.Response {
	err := r.db.Exec("update sys_user set del_flag = '2' where user_id in (?) ", userId).Error
	if err != nil {
		panic(response.ReturnFailMsg(err.Error()))
	}
	return response.ReturnSuccess("操作成功")
}

func (r *sysUserRepo) ChangeUserStatus(param system.SysUserParam) response.Response {
	data := make(map[string]interface{})

	if param.Status != "" {
		data["status"] = param.Status
	}

	//等价于: UPDATE `foods` SET `price` = '35', `stock` = '0'  WHERE (user_id = '2')
	err2 := r.db.Model(&system.SysUser{}).Where("user_id = ?", param.UserId).Updates(data)
	if err2.Error != nil {
		return response.ReturnFailMsg("修改失败")
	}

	return response.ReturnSuccess("修改成功")
}

func (r *sysUserRepo) ResetPwd(param system.SysUserParam) response.Response {
	data := make(map[string]interface{})

	if param.Password != "" {
		var pwd, _ = utils.PasswordHash(param.Password)
		data["password"] = pwd
	}

	//等价于: UPDATE `foods` SET `price` = '35', `stock` = '0'  WHERE (user_id = '2')
	err2 := r.db.Model(&system.SysUser{}).Where("user_id = ?", param.UserId).Updates(data)
	if err2.Error != nil {
		return response.ReturnFailMsg("修改失败")
	}

	return response.ReturnSuccess("修改成功")
}

func (r *sysUserRepo) FindUser(param system.LoginParam, context *gin.Context) {
	var loginName = param.UserName
	var pass = param.Password
	var user = r.FindUserByName(loginName)
	if user.UserId != 0 {
		if user.Status == "1" {
			SysLoginInfoRepository(r.db).LoginInfoAdd(context, param, "登录失败，账号已停用", false)
			context.JSON(http.StatusOK, response.ReturnFailMsg("账号已停用"))
			return
		}
		// 验证 密码是否正确
		if utils.PasswordVerify(pass, user.Password) {
			tokenString, err := middleware.CreateToken(user.UserId, user.DeptId)
			if err != nil {
				SysLoginInfoRepository(r.db).LoginInfoAdd(context, param, "登录失败，"+err.Error(), false)
				context.JSON(http.StatusOK, response.ReturnFailMsg("登录失败"))
				return
			}
			SysLoginInfoRepository(r.db).LoginInfoAdd(context, param, "登录成功", true)
			context.JSON(http.StatusOK, gin.H{
				"msg":   "登录成功",
				"code":  http.StatusOK,
				"token": tokenString,
			})
		} else {
			SysLoginInfoRepository(r.db).LoginInfoAdd(context, param, "登录失败，密码错误", false)
			context.JSON(http.StatusOK, gin.H{
				"msg":  "登录失败，密码错误",
				"code": http.StatusInternalServerError,
			})
		}

	} else {
		SysLoginInfoRepository(r.db).LoginInfoAdd(context, param, "登录失败，用户不存在", false)
		context.JSON(http.StatusOK, gin.H{
			"msg":  "用户不存在",
			"code": http.StatusInternalServerError,
		})
	}
}

func (r *sysUserRepo) UpdatePassWord(newPassWord string, user system.SysUser) {
	err2 := r.db.Model(&user).Update("password", newPassWord)
	if err2.Error != nil {
		panic(response.ReturnFailMsg("修改密码失败"))
	}
}

func (r *sysUserRepo) UpdateAvatar(Filename string, user system.SysUser) {
	err2 := r.db.Model(&user).Update("avatar", "/profile/"+Filename)
	if err2.Error != nil {
		panic(response.ReturnFailMsg("上传图片异常，请联系管理员"))
	}
}
